package cn.com.bsoft.mobile.service


import cn.com.bsoft.mobile.dao.AppMessageJobDao
import cn.com.bsoft.mobile.entity.AppMessageJob
import cn.com.bsoft.mobile.model.DeviceType

import cn.jiguang.common.ClientConfig
import org.springframework.beans.factory.annotation.Autowired
import javax.annotation.PostConstruct
import cn.jpush.api.JPushClient
import cn.jpush.api.push.model.Message
import cn.jpush.api.push.model.Platform
import cn.jpush.api.push.model.PushPayload
import cn.jpush.api.push.model.audience.Audience
import cn.jpush.api.push.model.notification.AndroidNotification
import cn.jpush.api.push.model.notification.Notification

import cn.net.xyan.blossom.core.service.ConfigService
import cn.net.xyan.blossom.kotlin.AllOpen

import org.springframework.scheduling.annotation.Async
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.transaction.annotation.Transactional
import java.util.*


@AllOpen
class JPushService {

    @Autowired
    lateinit var configService: ConfigService

    @Autowired
    lateinit var jobDao: AppMessageJobDao

    @Autowired
    lateinit var deviceService: MobileDeviceService

    lateinit var jpushClient: JPushClient

    companion object {
        const val KEYJPushAppID = "KEYJPushAppID"
        const val KEYJPushSecret = "KEYJPushSecret"
    }


    @PostConstruct
    fun setup() {

        configService.setupVariable(KEYJPushAppID, "382dc3ad7ba5311901ee9281", "极光推送AppID")
        configService.setupVariable(KEYJPushSecret, "f68219685f0ec2194761b35d", "极光推送Secret")

        val appID = configService.queryValue(KEYJPushAppID)

        val secret = configService.queryValue(KEYJPushSecret)

        jpushClient = JPushClient(secret, appID, null, ClientConfig.getInstance())

    }

    @Async
    fun doSendJobAsync(job: AppMessageJob) {
        doSendJob(job)
    }

    @Transactional
    fun doSendJob(job: AppMessageJob) {
        val now = Date()

        val msg = job.message
        val app = job.app

        val jPushID = deviceService.codeForNotifyPush(job.user, app, job.device)

        val msgBuilder = Message.newBuilder()
                .setTitle(msg.msgTitle)
                .setMsgContent(msg.messageBody)
                .addExtra("extra",msg.extra?:"")
                .addExtra("id",msg.messageID)


        val payload = PushPayload.newBuilder()
                .setPlatform(Platform.android())
                .setAudience(Audience.registrationId(jPushID))
                .setNotification(Notification
                        .newBuilder ()
                        .addPlatformNotification(AndroidNotification.newBuilder()
                                .setAlert(msg.msgTitle)
                                .setTitle(msg.messageBody)
                                .addExtras(mapOf(
                                        "extra" to (msg.extra?:""),
                                        "action" to (msg.action?:""),
                                        "id" to msg.messageID))
                                .build())
                        .build())
                .setMessage(msgBuilder.build())
                .build()
        try {
            val result = jpushClient.sendPush(payload)
            job.sentDate = Date()
        } catch (e: Throwable) {
            val diff = now.time - job.createDate.time
            val next = Date(now.time + diff * 2)
            job.nextSendDate = next
            job.retryCount = job.retryCount + 1
        }


        jobDao.saveAndFlush(job)
    }

    @Scheduled(cron = "0 0/1 * * * ?")
    fun scheduleSend() {
        val now = Date()

        val start = Date(now.time - 1000 * 3600 * 1)

        val jobs = jobDao.queryUnSent(DeviceType.Android.value, start, now)

        jobs.forEach {
            doSendJobAsync(it)
        }
    }
}